package org.raymond.icloud.common.starter.webFilter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.raymond.icloud.common.core.constants.ErrorCode;
import org.raymond.icloud.common.core.constants.CacheConstants;
import org.raymond.icloud.common.core.exception.BaseException;
import org.raymond.icloud.common.core.model.Principal;
import org.raymond.icloud.common.core.mybatis.UserIdContext;
import org.raymond.icloud.common.core.util.ApplicationContextUtils;
import org.raymond.icloud.common.core.util.RedisUtil;
import org.raymond.icloud.common.core.util.RequestUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.HandlerExceptionResolver;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class AuthenticationFilter extends AbstractFilter {

    private static final String adminLogoutPath = "/admin/user/logout";

    private HandlerExceptionResolver resolver;
    private RedisUtil redisUtil;

    @Override
    protected void initFilterBean() throws ServletException {
        ApplicationContext ctx = ApplicationContextUtils.getApplicationContext();
        resolver = ctx.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
        redisUtil = ctx.getBean("redisUtil", RedisUtil.class);
    }

    @Override
    protected void doFilterSub(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = RequestUtil.resolve(request);
        if (StringUtils.isBlank(token)) {
            log.error("token必填");
            resolver.resolveException(request, response, null, new BaseException(ErrorCode.UNAUTHORIZED.getCode(), "token必填"));
            return;
        }
        Object obj = redisUtil.get(CacheConstants.PREFIX_CERT + token);
        if (obj == null) {
            log.error("token[{}]未找到登陆凭证", token);
            resolver.resolveException(request, response, null, new BaseException(ErrorCode.UNAUTHORIZED.getCode(), "token错误"));
            return;
        }

        Principal principal = (Principal) obj;
        Long userId = principal.getId();
        UserIdContext.setUserId(userId);
        filterChain.doFilter(request, response);
        UserIdContext.clear();
        String requestUri = RequestUtil.getRelativePath(request);
        if(isLogout(requestUri)){
            redisUtil.set(CacheConstants.PREFIX_CERT + token, null);
        }
    }

    private boolean isLogout(String requestPath){
        return adminLogoutPath.equalsIgnoreCase(requestPath);
    }
}
